package gp;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.List;

import measures.GaussianKernel;
import measures.PolyKernel;
import probability.GaussianDistribution;
import utils.Printer;
import basics.Dataset;
import basics.DenseMatrix;
import basics.DenseVector;
import basics.Matrix;
import basics.Vector;
import basics.VectorMatrix;
import classification.Classifier;

public class Classification extends Classifier<Integer> {

	public static GaussianDistribution predictReg(Vector kx, Matrix k_inverse, Vector y, double k) {
		double a = kx.times(k_inverse).times(y).sumAllElements();
		return new GaussianDistribution(a, k - kx.times(k_inverse).times(kx.transpose()).sumAllElements());
	}

	private DenseMatrix _k;
	private GaussianKernel _gk;
	private Dataset<Vector, Integer> _ds;
	private DenseVector _y;

	@Override
	public Integer predict(VectorMatrix v) {
		Vector vv = (Vector) v;
		DenseVector kx = _gk.measure(vv, _ds.features());
		GaussianDistribution g = predictReg(kx, _k, _y, _gk.measure(vv, vv));
		return g.getMu() > .5 ? 1 : -1;
	}

	@Override
	public void train(Dataset<Vector, Integer> ds) {
		_ds = ds;
		_gk = new GaussianKernel(10);
		_k = _gk.getMatrix(ds.features());
		_k = (DenseMatrix) _k.inverse();
		_y = buildY(ds.classes());

		try {
			Printer.print(new PrintStream("k"), _k);
			Printer.print(new PrintStream("y"), _y);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		// trainEP();
	}

	private void trainEP() {
		do {
			for (int i = 0; i < _ds.size(); i++) {

			}
		} while (!isConverged());
	}

	private boolean isConverged() {
		// TODO Auto-generated method stub
		return false;
	}

	private DenseVector buildY(List<Integer> classes) {
		DenseVector v = new DenseVector(classes.size());
		for (int i = 0; i < classes.size(); i++) {
			v.set(classes.get(i) > 0 ? 1. : -1., i);
		}

		return (DenseVector) v.transpose();
	}
}